package com.ruoyi.util;

import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Map;
import java.util.TreeMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * API鉴权工具类
 * 支持签名验证的HTTP请求
 * 
 * @author TooBit
 * @date 2025-01-06
 */
public class ApiAuthenticationUtils {
    
    private static final Logger log = LoggerFactory.getLogger(ApiAuthenticationUtils.class);
    
    /**
     * 鉴权类型枚举
     */
    public enum AuthType {
        NONE,           // 无需鉴权
        MARKET_DATA,    // 需要API-Key
        USER_STREAM,    // 需要API-Key
        USER_DATA,      // 需要API-Key和签名
        TRADE          // 需要API-Key和签名
    }
    
    /**
     * API配置类
     */
    public static class ApiConfig {
        private String baseUrl;
        private String accessKey;
        private String secretKey;
        private long recvWindow = 5000; // 默认5秒时间窗口
        
        public ApiConfig(String baseUrl, String accessKey, String secretKey) {
            this.baseUrl = baseUrl;
            this.accessKey = accessKey;
            this.secretKey = secretKey;
        }
        
        // Getters and Setters
        public String getBaseUrl() { return baseUrl; }
        public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; }
        public String getAccessKey() { return accessKey; }
        public void setAccessKey(String accessKey) { this.accessKey = accessKey; }
        public String getSecretKey() { return secretKey; }
        public void setSecretKey(String secretKey) { this.secretKey = secretKey; }
        public long getRecvWindow() { return recvWindow; }
        public void setRecvWindow(long recvWindow) { this.recvWindow = recvWindow; }
    }
    
    /**
     * 发送带鉴权的GET请求
     * 
     * @param config API配置
     * @param endpoint 接口端点（如：/api/v1/exchangeInfo）
     * @param params 请求参数
     * @param authType 鉴权类型
     * @return 响应结果
     */
    public static String sendAuthenticatedGet(ApiConfig config, String endpoint, Map<String, String> params, AuthType authType) {
        try {
            // 构建完整URL
            String fullUrl = config.getBaseUrl() + endpoint;
            
            // 添加时间戳（对于需要签名的接口）
            if (authType == AuthType.USER_DATA || authType == AuthType.TRADE) {
                if (params == null) {
                    params = new TreeMap<>();
                }
                params.put("timestamp", String.valueOf(System.currentTimeMillis()));
                params.put("recvWindow", String.valueOf(config.getRecvWindow()));
            }
            
            // 构建查询字符串
            String queryString = buildQueryString(params);
            if (!queryString.isEmpty()) {
                fullUrl += "?" + queryString;
            }
            
            log.info("🚀 发送API请求: {}", fullUrl);
            
            // 创建HTTP连接
            URL url = new URL(fullUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("User-Agent", "TooBit-Monitor/1.0");
            
            // 添加API-Key头（除了NONE类型）
            if (authType != AuthType.NONE) {
                connection.setRequestProperty("X-BB-APIKEY", config.getAccessKey());
                log.info("🔑 添加API-Key: {}", config.getAccessKey().substring(0, 10) + "...");
            }
            
            // 添加签名（对于需要签名的接口）
            if (authType == AuthType.USER_DATA || authType == AuthType.TRADE) {
                String signature = generateSignature(config.getSecretKey(), queryString);
                // 将签名添加到URL中
                fullUrl += (queryString.isEmpty() ? "?" : "&") + "signature=" + signature;
                url = new URL(fullUrl);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setRequestProperty("User-Agent", "TooBit-Monitor/1.0");
                connection.setRequestProperty("X-BB-APIKEY", config.getAccessKey());
                
                log.info("🔐 添加签名: {}", signature.substring(0, 10) + "...");
                log.info("📋 最终请求URL: {}", fullUrl);
            }
            
            // 发送请求
            int responseCode = connection.getResponseCode();
            log.info("📊 HTTP响应码: {}", responseCode);
            
            // 读取响应
            BufferedReader reader;
            if (responseCode >= 200 && responseCode < 300) {
                reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
            } else {
                reader = new BufferedReader(new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8));
            }
            
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            reader.close();
            
            String result = response.toString();
            if (responseCode >= 200 && responseCode < 300) {
                log.info("✅ 请求成功，响应长度: {} 字符", result.length());
                if (result.length() > 200) {
                    log.info("📄 响应内容预览: {}...", result.substring(0, 200));
                } else {
                    log.info("📄 完整响应: {}", result);
                }
            } else {
                log.error("❌ 请求失败: {}", result);
            }
            
            return result;
            
        } catch (Exception e) {
            log.error("🚨 API请求异常: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 生成HMAC SHA256签名
     * 
     * @param secretKey 密钥
     * @param data 待签名数据
     * @return 签名字符串
     */
    private static String generateSignature(String secretKey, String data) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            mac.init(keySpec);
            byte[] signature = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            
            // 转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : signature) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            log.error("🚨 签名生成失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 构建查询字符串
     * 
     * @param params 参数Map
     * @return 查询字符串
     */
    private static String buildQueryString(Map<String, String> params) {
        if (params == null || params.isEmpty()) {
            return "";
        }
        
        StringBuilder queryString = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (queryString.length() > 0) {
                queryString.append("&");
            }
            queryString.append(entry.getKey()).append("=").append(entry.getValue());
        }
        return queryString.toString();
    }
    
    /**
     * 发送POST请求（暂时保留接口，未实现）
     */
    public static String sendAuthenticatedPost(ApiConfig config, String endpoint, Map<String, String> params, String body, AuthType authType) {
        // TODO: 实现POST请求
        throw new UnsupportedOperationException("POST请求暂未实现");
    }
}